package com.mercury.flowable.controller;

import com.mercury.flowable.domain.FlowTaskReq;
import com.mercury.flowable.enums.FlowComment;
import com.mercury.flowable.factory.FlowServiceFactory;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * @author mercury
 * @date 2022/8/16 10:15
 */
@RestController
@Slf4j
public class FlowAbleController extends FlowServiceFactory {

    private static final String BPMN_FILE_SUFFIX = ".bpmn";


    @GetMapping("/startBy/{procDefId}")
    public void startProcessInstanceById(@PathVariable("procDefId") String procDefId) {
        try {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(procDefId)
                    .latestVersion().singleResult();
            if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) {
                log.info("流程已被挂起,请先激活流程");
                return;
            }
            identityService.setAuthenticatedUserId("1");
            ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId);
            Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult();
            if (Objects.nonNull(task)) {
                taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), "张闯" + "发起流程申请");
            }
            log.info("流程启动成功");
        } catch (Exception e) {
            e.printStackTrace();
            log.info("流程启动错误");
        }
    }

    @SneakyThrows
    @GetMapping("/readXml/{deployId}")
    public String readXml(@PathVariable("deployId") String deployId) {
        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
        InputStream inputStream = repositoryService.getResourceAsStream(definition.getDeploymentId(), definition.getResourceName());
        return IOUtils.toString(inputStream, StandardCharsets.UTF_8.name());
    }


    /**
     * 导入流程文件
     */
    @ApiOperation(value = "导入流程文件", notes = "上传bpmn20的xml文件")
    @PostMapping("/import")
    public void importFile(@RequestParam(required = false) String name,
                           @RequestParam(required = false) String category,
                           MultipartFile file) throws IOException {
        InputStream in = file.getInputStream();
        Deployment deploy = repositoryService.createDeployment().addInputStream(name + BPMN_FILE_SUFFIX, in).name(name).category(category).deploy();
        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
        repositoryService.setProcessDefinitionCategory(definition.getId(), category);
    }



    @PostMapping("/complete")
    public void complete(@RequestBody FlowTaskReq flowTaskReq) {
        Task task = taskService.createTaskQuery().taskId(flowTaskReq.getTaskId()).singleResult();
        if (Objects.isNull(task)) {
            return;
        }
        if (DelegationState.PENDING.equals(task.getDelegationState())) {
            taskService.addComment(flowTaskReq.getTaskId(), flowTaskReq.getInstanceId(), FlowComment.DELEGATE.getType(), flowTaskReq.getComment());
            taskService.resolveTask(flowTaskReq.getTaskId(), flowTaskReq.getValues());
        } else {
            taskService.addComment(flowTaskReq.getTaskId(), flowTaskReq.getInstanceId(), FlowComment.NORMAL.getType(), flowTaskReq.getComment());
            taskService.complete(flowTaskReq.getTaskId(), flowTaskReq.getValues());
        }
        log.info("ok");
    }


}
